home *** CD-ROM | disk | FTP | other *** search
/ Atari Mega Archive 1 / Atari Mega Archive - Volume 1.iso / mint / mint110s.zoo / unifs.c < prev    next >
C/C++ Source or Header  |  1994-02-11  |  19KB  |  808 lines

  1. /*
  2. Copyright 1991,1992 Eric R. Smith.
  3. Copyright 1992,1993,1994 Atari Corporation.
  4. All rights reserved.
  5.  */
  6.  
  7. /* a simple unified file system */
  8.  
  9. #include "mint.h"
  10.  
  11.  
  12. extern FILESYS bios_filesys, proc_filesys, pipe_filesys, shm_filesys;
  13.  
  14. static long    ARGS_ON_STACK uni_root    P_((int drv, fcookie *fc));
  15. static long    ARGS_ON_STACK uni_lookup    P_((fcookie *dir, const char *name, fcookie *fc));
  16. static long    ARGS_ON_STACK uni_getxattr    P_((fcookie *fc, XATTR *xattr));
  17. static long    ARGS_ON_STACK uni_chattr    P_((fcookie *fc, int attrib));
  18. static long    ARGS_ON_STACK uni_chown    P_((fcookie *fc, int uid, int gid));
  19. static long    ARGS_ON_STACK uni_chmode    P_((fcookie *fc, unsigned mode));
  20. static long    ARGS_ON_STACK uni_rmdir    P_((fcookie *dir, const char *name));
  21. static long    ARGS_ON_STACK uni_remove    P_((fcookie *dir, const char *name));
  22. static long    ARGS_ON_STACK uni_getname    P_((fcookie *root, fcookie *dir,
  23.                             char *pathname, int size));
  24. static long    ARGS_ON_STACK uni_rename    P_((fcookie *olddir, char *oldname,
  25.                     fcookie *newdir, const char *newname));
  26. static long    ARGS_ON_STACK uni_opendir    P_((DIR *dirh, int flags));
  27. static long    ARGS_ON_STACK uni_readdir    P_((DIR *dirh, char *nm, int nmlen, fcookie *));
  28. static long    ARGS_ON_STACK uni_rewinddir    P_((DIR *dirh));
  29. static long    ARGS_ON_STACK uni_closedir    P_((DIR *dirh));
  30. static long    ARGS_ON_STACK uni_pathconf    P_((fcookie *dir, int which));
  31. static long    ARGS_ON_STACK uni_dfree    P_((fcookie *dir, long *buf));
  32. static DEVDRV *    ARGS_ON_STACK uni_getdev    P_((fcookie *fc, long *devsp));
  33. static long    ARGS_ON_STACK uni_symlink    P_((fcookie *dir, const char *name, const char *to));
  34. static long    ARGS_ON_STACK uni_readlink    P_((fcookie *fc, char *buf, int buflen));
  35. static long    ARGS_ON_STACK uni_fscntl    P_((fcookie *dir, const char *name, int cmd, long arg));
  36.  
  37. FILESYS uni_filesys = {
  38.     (FILESYS *)0,
  39.     FS_LONGPATH,
  40.     uni_root,
  41.     uni_lookup, nocreat, uni_getdev, uni_getxattr,
  42.     uni_chattr, uni_chown, uni_chmode,
  43.     nomkdir, uni_rmdir, uni_remove, uni_getname, uni_rename,
  44.     uni_opendir, uni_readdir, uni_rewinddir, uni_closedir,
  45.     uni_pathconf, uni_dfree, nowritelabel, noreadlabel,
  46.     uni_symlink, uni_readlink, nohardlink, uni_fscntl, nodskchng
  47. };
  48.  
  49. /*
  50.  * structure that holds files
  51.  * if (mode & S_IFMT == S_IFDIR), then this is an alias for a drive:
  52.  *    "dev" holds the appropriate BIOS device number, and
  53.  *    "data" is meaningless
  54.  * if (mode & S_IFMT == S_IFLNK), then this is a symbolic link:
  55.  *    "dev" holds the user id of the owner, and
  56.  *    "data" points to the actual link data
  57.  */
  58.  
  59. typedef struct unifile {
  60.     char name[NAME_MAX+1];
  61.     ushort mode;
  62.     ushort dev;
  63.     FILESYS *fs;
  64.     void *data;
  65.     struct unifile *next;
  66. } UNIFILE;
  67.  
  68. static UNIFILE u_drvs[UNI_NUM_DRVS];
  69. static UNIFILE *u_root = 0;
  70.  
  71. static long    do_ulookup    P_((fcookie *, const char *, fcookie *, UNIFILE **));
  72.  
  73. FILESYS *
  74. get_filesys (dev)
  75.      int dev;
  76. {
  77.   UNIFILE *u;
  78.  
  79.   for (u = u_root; u; u = u->next)
  80.     if (u->dev == dev)
  81.       return u->fs;
  82.   return (FILESYS *) 0L;
  83. }
  84.  
  85. void
  86. unifs_init()
  87. {
  88.     UNIFILE *u = u_drvs;
  89.     int i;
  90.  
  91.     u_root = u;
  92.     for (i = 0; i < UNI_NUM_DRVS; i++,u++) {
  93.         u->next = u+1;
  94.         u->mode = S_IFDIR|DEFAULT_DIRMODE;
  95.         u->dev = i;
  96.         if (i == PROCDRV) {
  97.             strcpy(u->name, "proc");
  98.             u->fs = &proc_filesys;
  99.         } else if (i == PIPEDRV) {
  100.             strcpy(u->name, "pipe");
  101.             u->fs = &pipe_filesys;
  102.         } else if (i == BIOSDRV) {
  103.             strcpy(u->name, "dev");
  104.             u->fs = &bios_filesys;
  105.         } else if (i == UNIDRV) {
  106.             (u-1)->next = u->next;    /* skip this drive */
  107.         } else if (i == SHMDRV) {
  108.             strcpy(u->name, "shm");
  109.             u->fs = &shm_filesys;
  110.         } else {
  111.             u->name[0] = i + 'a';
  112.             u->name[1] = 0;
  113.             u->fs = 0;
  114.         }
  115.     }
  116.     --u;    /* oops, we went too far */
  117.     u->next = 0;
  118. }
  119.  
  120. static long ARGS_ON_STACK 
  121. uni_root(drv, fc)
  122.     int drv;
  123.     fcookie *fc;
  124. {
  125.     if (drv == UNIDRV) {
  126.         fc->fs = &uni_filesys;
  127.         fc->dev = drv;
  128.         fc->index = 0L;
  129.         return 0;
  130.     }
  131.     fc->fs = 0;
  132.     return EINTRN;
  133. }
  134.  
  135. static long ARGS_ON_STACK 
  136. uni_lookup(dir, name, fc)
  137.     fcookie *dir;
  138.     const char *name;
  139.     fcookie *fc;
  140. {
  141.     return do_ulookup(dir, name, fc, (UNIFILE **)0);
  142. }
  143.  
  144. /* worker function for uni_lookup; can also return the UNIFILE
  145.  * pointer for the root directory
  146.  */
  147. static long
  148. do_ulookup(dir, name, fc, up)
  149.     fcookie *dir;
  150.     const char *name;
  151.     fcookie *fc;
  152.     UNIFILE **up;
  153. {
  154.     UNIFILE *u;
  155.     long drvs;
  156.     FILESYS *fs;
  157.     fcookie *tmp;
  158.     extern long dosdrvs;
  159.  
  160.     TRACE(("uni_lookup(%s)", name));
  161.  
  162.     if (dir->index != 0) {
  163.         DEBUG(("uni_lookup: bad directory"));
  164.         return EPTHNF;
  165.     }
  166. /* special case: an empty name in a directory means that directory */
  167. /* so do "." and ".." */
  168.  
  169.     if (!*name || !strcmp(name, ".") || !strcmp(name, "..")) {
  170.         dup_cookie(fc, dir);
  171.         return 0;
  172.     }
  173.     drvs = drvmap() | dosdrvs | PSEUDODRVS;
  174. /*
  175.  * OK, check the list of aliases and special directories
  176.  */
  177.     for (u = u_root; u; u = u->next) {
  178.         if (!stricmp(name, u->name)) {
  179.             if ( (u->mode & S_IFMT) == S_IFDIR ) {
  180.                 if (u->dev >= NUM_DRIVES) {
  181.                     fs = u->fs;
  182.                     if (up) *up = u;
  183.                     return (*fs->root)(u->dev,fc);
  184.                 }
  185.                 if ((drvs & (1L << u->dev)) == 0)
  186.                     return EPTHNF;
  187.                 tmp = &curproc->root[u->dev];
  188.                 if (!tmp->fs) {        /* drive changed? */
  189.                     changedrv(tmp->dev);
  190.                     tmp = &curproc->root[u->dev];
  191.                     if (!tmp->fs)
  192.                         return EPTHNF;
  193.                 }
  194.                 dup_cookie(fc, tmp);
  195.             } else {        /* a symbolic link */
  196.                 fc->fs = &uni_filesys;
  197.                 fc->dev = UNIDRV;
  198.                 fc->index = (long)u;
  199.             }
  200.             if (up) *up = u;
  201.             return 0;
  202.         }
  203.     }
  204.     DEBUG(("uni_lookup: name (%s) not found", name));
  205.     return EFILNF;
  206. }
  207.  
  208. static long ARGS_ON_STACK 
  209. uni_getxattr(fc, xattr)
  210.     fcookie *fc;
  211.     XATTR *xattr;
  212. {
  213.     UNIFILE *u = (UNIFILE *)fc->index;
  214.  
  215.     if (fc->fs != &uni_filesys) {
  216.         ALERT("ERROR: wrong file system getxattr called");
  217.         return EINTRN;
  218.     }
  219.  
  220.     xattr->index = fc->index;
  221.     xattr->dev = fc->dev;
  222.     xattr->nlink = 1;
  223.     xattr->blksize = 1;
  224.  
  225. /* If "u" is null, then we have the root directory, otherwise
  226.  * we use the UNIFILE structure to get the info about it
  227.  */
  228.     if (!u || ( (u->mode & S_IFMT) == S_IFDIR )) {
  229.         xattr->uid = xattr->gid = 0;
  230.         xattr->size = xattr->nblocks = 0;
  231.         xattr->mode = S_IFDIR | DEFAULT_DIRMODE;
  232.         xattr->attr = FA_DIR;
  233.     } else {
  234.         xattr->uid = u->dev;
  235.         xattr->gid = 0;
  236.         xattr->size = xattr->nblocks = strlen(u->data) + 1;
  237.         xattr->mode = u->mode;
  238.         xattr->attr = 0;
  239.     }
  240.     xattr->mtime = xattr->atime = xattr->ctime = 0;
  241.     xattr->mdate = xattr->adate = xattr->cdate = 0;
  242.     return 0;
  243. }
  244.  
  245. static long ARGS_ON_STACK 
  246. uni_chattr(dir, attrib)
  247.     fcookie *dir;
  248.     int attrib;
  249. {
  250.     UNUSED(dir); UNUSED(attrib);
  251.     return EACCDN;
  252. }
  253.  
  254. static long ARGS_ON_STACK 
  255. uni_chown(dir, uid, gid)
  256.     fcookie *dir;
  257.     int uid, gid;
  258. {
  259.     UNUSED(dir); UNUSED(uid);
  260.     UNUSED(gid);
  261.     return EINVFN;
  262. }
  263.  
  264. static long ARGS_ON_STACK 
  265. uni_chmode(dir, mode)
  266.     fcookie *dir;
  267.     unsigned mode;
  268. {
  269.     UNUSED(dir);
  270.     UNUSED(mode);
  271.     return EINVFN;
  272. }
  273.  
  274. static long ARGS_ON_STACK 
  275. uni_rmdir(dir, name)
  276.     fcookie *dir;
  277.     const char *name;
  278. {
  279.     long r;
  280.  
  281.     r = uni_remove(dir, name);
  282.     if (r == EFILNF) r = EPTHNF;
  283.     return r;
  284. }
  285.  
  286. static long ARGS_ON_STACK 
  287. uni_remove(dir, name)
  288.     fcookie *dir;
  289.     const char *name;
  290. {
  291.     UNIFILE *u, *lastu;
  292.  
  293.     UNUSED(dir);
  294.  
  295.     lastu = 0;
  296.     u = u_root;
  297.     while (u) {
  298.         if (!strncmp(u->name, name, NAME_MAX)) {
  299.             if ( (u->mode & S_IFMT) != S_IFLNK ) return EFILNF;
  300.             kfree(u->data);
  301.             if (lastu)
  302.                 lastu->next = u->next;
  303.             else
  304.                 u_root = u->next;
  305.             kfree(u);
  306.             return 0;
  307.         }
  308.         lastu = u;
  309.         u = u->next;
  310.     }
  311.     return EFILNF;
  312. }
  313.  
  314. static long ARGS_ON_STACK 
  315. uni_getname(root, dir, pathname, size)
  316.     fcookie *root, *dir; char *pathname;
  317.     int size;
  318. {
  319.     FILESYS *fs;
  320.     UNIFILE *u;
  321.     char *n;
  322.     fcookie relto;
  323.     char tmppath[PATH_MAX];
  324.     long r;
  325.  
  326.     UNUSED(root);
  327.  
  328.     if (size <= 0) return ERANGE;
  329.  
  330.     fs = dir->fs;
  331.     if (dir->dev == UNIDRV) {
  332.         *pathname = 0;
  333.         return 0;
  334.     }
  335.  
  336.     for (u = u_root; u; u = u->next) {
  337.         if (dir->dev == u->dev && (u->mode & S_IFMT) == S_IFDIR) {
  338.             *pathname++ = '\\';
  339.             if (--size <= 0) return ERANGE;
  340.             for (n = u->name; *n; ) {
  341.                 *pathname++ = *n++;
  342.